package pl.edu.agh.iosr.gamblingzone.validators.dao.ejb;

import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Random;

import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;

import pl.edu.agh.iosr.gamblingzone.commons.DataGenerator;
import pl.edu.agh.iosr.gamblingzone.commons.DataGeneratorBean;
import pl.edu.agh.iosr.gamblingzone.model.AbstractEvent;
import pl.edu.agh.iosr.gamblingzone.model.Bet;
import pl.edu.agh.iosr.gamblingzone.model.BettingSlip;
import pl.edu.agh.iosr.gamblingzone.model.User;
import pl.edu.agh.iosr.gamblingzone.validators.tests.Tests;

/**
 * The Class Fetching. <br>
 * This test fetch data from database. It checks if lazy initialization occurs.
 */
public class Fetching extends Tests {
	
	/** The was data generated. */
	private static boolean wasDataGenerated = false;

	
	/**
	 * Run generate data.
	 */
	public void runGenerateData() {
		DataGenerator dataGenerator = new DataGeneratorBean();
		dataGenerator.setEntityManager(entityManager);
		
		dataGenerator.generateData();
		wasDataGenerated = true;
	}
	
	/**
	 * Generate data.
	 */
	@Before
	public void generateData() {
		if (entityManager == null) {
			throw new IllegalStateException("Entity manager should be set up first");
		}
		if (!wasDataGenerated) {
			runGenerateData();
		}
	}
	
	/**
	 * Test generated.
	 */
	@Test
	public void testGenerated() {
		Assert.assertTrue(userDAO.getEntitiesCount() > 0);
	}
	
	/**
	 * Retrieve users.
	 * 
	 * @throws Exception the exception
	 */
	@Test
	public void retrieveUsers() throws Exception {
		List<User> userList = userDAO.findAll();
		
		tm.commit();
		
		for (User u: userList) {
			System.out.println(u.getFirstName());
		}
		
		tm.begin();
	}
	
	/**
	 * Retrieve betting slips.
	 * 
	 * @throws Exception the exception
	 */
	@Test
	public void retrieveBettingSlips() throws Exception {
		// retrieve random user
		Random random = new Random();
		int userId = Math.abs(random.nextInt(userDAO.getEntitiesCount()));
		User randomUser = userDAO.findAll().get(userId);
		String userLogin = randomUser.getLoginName();
		
		List<BettingSlip> bettList = bettingSlipDAO.findAll(randomUser, 0);
		
		tm.commit();
		tm.begin();
		
		System.out.println("BettingSlips for user: "+userLogin);
		for (BettingSlip bs: bettList) {
			System.out.println("\t"+bs.hashCode());
		}
	}
	
	/**
	 * Retrieve bets from temp betting slip.
	 * 
	 * @throws Exception the exception
	 */
	@Test
	public void retrieveBetsFromTempBettingSlip() throws Exception {
		// retrieve random user
		Random random = new Random();
		int userId = Math.abs(random.nextInt(userDAO.getEntitiesCount()));
		User randomUser = userDAO.findAll().get(userId);
		String userLogin = randomUser.getLoginName();
		
		List<Bet> bettList = betDAO.findAll(randomUser.getTempBettingSlip(), 0);
		
		tm.commit();
		tm.begin();
		
		System.out.println("Bets from tempBettingSlip for user: "+userLogin);
		for (Bet b: bettList) {
			System.out.println("\t"+b.hashCode());
		}
	}
	
	/**
	 * Retrieve bets from betting slips.
	 * 
	 * @throws Exception the exception
	 */
	@Test
	public void retrieveBetsFromBettingSlips() throws Exception {
		// retrieve random user
		Random random = new Random();
		int userId = Math.abs(random.nextInt(userDAO.getEntitiesCount()));
		User randomUser = userDAO.findAll().get(userId);
		String userLogin = randomUser.getLoginName();
		
		bettingSlipDAO.setPageSize(100);
		List<BettingSlip> slipsList = bettingSlipDAO.findAll(randomUser, 0);
		Map<BettingSlip, List<Bet>> betsMap = new HashMap<BettingSlip, List<Bet>>();
		
		for (BettingSlip bs: slipsList) {
			List<Bet> bettList = betDAO.findAll(bs, 0);
			betsMap.put(bs, bettList);
		}
		
		tm.commit();
		tm.begin();
		
		System.out.println("Bets for given Bettingslip of user: "+userLogin);
		for (BettingSlip bs: slipsList) {
			System.out.println("\tBetting slip"+bs.hashCode());
			
			for (Bet b: betsMap.get(bs)) {
				System.out.println("\t\tBet: "+b.hashCode());
			}
		}
	}
	
	/**
	 * Retrieve events from bets.
	 * 
	 * @throws Exception the exception
	 */
	@Test
	public void retrieveEventsFromBets() throws Exception {
		// retrieve random user
		Random random = new Random();
		int userId = Math.abs(random.nextInt(userDAO.getEntitiesCount()));
		User randomUser = userDAO.findAll().get(userId);
		String userLogin = randomUser.getLoginName();
		
		bettingSlipDAO.setPageSize(100);
		List<BettingSlip> slipsList = bettingSlipDAO.findAll(randomUser, 0);
		Map<BettingSlip, List<Bet>> betsMap = new HashMap<BettingSlip, List<Bet>>();
		
		for (BettingSlip bs: slipsList) {
			List<Bet> bettList = betDAO.findAll(bs, 0);
			betsMap.put(bs, bettList);
		}
		
		tm.commit();
		tm.begin();
		
		System.out.println("Bets for given Bettingslip of user: "+userLogin);
		for (BettingSlip bs: slipsList) {
			System.out.println("\tBetting slip"+bs.hashCode());
			
			for (Bet b: betsMap.get(bs)) {
				System.out.println("\t\tBet: "+b.hashCode());
				
				for (AbstractEvent ae: b.getEvents()) {
					System.out.println("\t\t\tevent: "+ae.hashCode());
				}
			}
		}
	}
}
